home *** CD-ROM | disk | FTP | other *** search
Modula Implementation | 1996-08-17 | 5.3 KB | 218 lines |
- (* Converted from C-Example in RKM-Companion 2.04 *)
-
- IMPLEMENTATION MODULE CiaTimer;
-
- IMPORT Arts;
- IMPORT CR: Resources;
- IMPORT HW: Hardware;
- IMPORT ED: ExecD;
- IMPORT EL: ExecL;
- IMPORT R;
- FROM SYSTEM IMPORT ADDRESS, ADR, CAST, ASSEMBLE;
-
- (*$ EntryClear:= FALSE
- NilChk:= FALSE
- StackChk:= FALSE
- RangeChk:= FALSE
- OverflowChk:= FALSE
- *)
-
-
-
- TYPE
- FreeTimer= RECORD
- ciaBase: ED.LibraryPtr;
- timerBit: HW.CiaIcrFlags;
- ciaP: POINTER TO HW.CIAA;
- stopMask: HW.CiaCraFlagSet;
- startMask: HW.CiaCraFlagSet;
- ciaCr: POINTER TO HW.CiaCraFlagSet;
- ciaHi: POINTER TO SHORTCARD;
- ciaLo: POINTER TO SHORTCARD;
- oldAbleMask: HW.CiaIcrFlagSet;
- gotIt: BOOLEAN;
- END;
-
-
- VAR
- FreeT: FreeTimer;
- StopCounter: CARDINAL;
-
-
- (* Start- and StopTimer are coded in assembler to make them as
- small as possible, because they should not use much cache space *)
- (*$EntryExitCode:= FALSE*)
- (*$LoadA4:= TRUE*)
- PROCEDURE CiaStartTimer;
- (*VAR
- a2{R.A0}: ADDRESS;
- a4{R.D0}: ADDRESS;*)
- BEGIN
- (* Partly setup is done in TryTimer, contrary to C-Example *)
- (*EL.Disable;*)
- (*FreeT.ciaCr^:= FreeT.ciaCr^ * FreeT.stopMask;*)
- ASSEMBLE(MOVE.B FreeT.stopMask(A4), D0
- MOVE.L FreeT.ciaCr(A4), A1
- AND.B D0, (A1)
- END);
- (*EL.Enable;*)
- (*FreeT.ciaLo^:= 255;
- FreeT.ciaHi^:= 255;*)
- ASSEMBLE(MOVE.L FreeT.ciaLo(A4), A0
- MOVE.B #255, (A0)
- MOVE.L FreeT.ciaHi(A4), A0
- MOVE.B #255, (A0)
- END);
- (* FreeT.ciaCr^:= FreeT.ciaCr^ + FreeT.startMask;*)
- ASSEMBLE(MOVE.B FreeT.startMask(A4), D0
- (*MOVE.L FreeT.ciaCr(A4), A0*)
- OR.B D0, (A1)
- RTS
- END);
-
- END CiaStartTimer;
-
-
-
- (*$EntryExitCode:= FALSE*)
- (*$LoadA4:= TRUE*)
- PROCEDURE CiaStopTimer;
- (*VAR
- a1{R.D0}: LONGCARD;
- a2{R.A0}: ADDRESS;
- a3{R.D1}: LONGCARD;*)
- BEGIN
-
- ASSEMBLE(MOVE.B FreeT.stopMask(A4), D0
- MOVE.L FreeT.ciaCr(A4), A0
- AND.B D0, (A0)
- END);
- (*EL.Disable;*)
- (*FreeT.ciaCr^:= FreeT.ciaCr^ * FreeT.stopMask;*)
- (*EL.Enable;*)
- ASSEMBLE(MOVE.L FreeT.ciaHi(A4), A0
- MOVEQ #0, D0
- MOVE.B (A0), D0
- MOVE.L #256, D1
- MULU.W D0, D1
- MOVE.L FreeT.ciaLo(A4), A0
- MOVE.B (A0), D0
- ADD.W D0, D1
- MOVE.W D1, StopCounter(A4)
- RTS
- END);
- (*StopCounter:= CARDINAL(FreeT.ciaHi^)*256 + CARDINAL(FreeT.ciaLo^);*)
- END CiaStopTimer;
-
-
- PROCEDURE CiaGetDiff(): LONGINT;
- BEGIN
- RETURN LONGINT(65535-StopCounter);
- END CiaGetDiff;
-
-
-
- (*
- * Try to obtain a free interval timer on a CIA.
- *)
- PROCEDURE TryTimer(VAR Ft: FreeTimer): BOOLEAN;
- BEGIN
- EL.Disable;
-
- IF NIL = CR.AddICRVector(Ft.ciaBase, HW.ta, NIL) THEN
- Ft.timerBit:= HW.ta;
- Ft.oldAbleMask:= CR.AbleICR(Ft.ciaBase, HW.CiaIcrFlagSet{HW.ta});
- Ft.ciaCr:= ADR(Ft.ciaP^.cra);
- Ft.ciaHi:= ADR(Ft.ciaP^.tahi);
- Ft.ciaLo:= ADR(Ft.ciaP^.talo);
- Ft.startMask:= HW.CiaCraFlagSet{HW.craStart, HW.craRunmode};
- Ft.stopMask:= HW.CiaCraFlagSet{HW.craTodin, HW.craSpmode, HW.craRunmode, HW.craOutmode, HW.craPbon};
-
- ELSIF NIL = CR.AddICRVector(Ft.ciaBase, HW.tb, NIL) THEN
- Ft.timerBit:= HW.tb;
- Ft.oldAbleMask:= CR.AbleICR(Ft.ciaBase, HW.CiaIcrFlagSet{HW.tb});
- Ft.ciaCr:= ADR(Ft.ciaP^.crb);
- Ft.ciaHi:= ADR(Ft.ciaP^.tbhi);
- Ft.ciaLo:= ADR(Ft.ciaP^.talo);
- Ft.startMask:= CAST(HW.CiaCraFlagSet, HW.CiaCrbFlagSet{HW.crbStart, HW.crbRunmode});
- Ft.stopMask:= CAST(HW.CiaCraFlagSet, HW.CiaCrbFlagSet{HW.crbAlarm, HW.crbRunmode, HW.crbOutmode, HW.crbPbon});
-
- ELSE
- EL.Enable;
- RETURN FALSE;
- END;
-
- EL.Enable;
- RETURN TRUE;
- END TryTimer;
-
-
- (*
- * A routine to find a free interval timer.
- *
- * This routine makes no assumptions about which interval timers
- * (if any) are available for use. Currently there are two interval
- * timers per CIA chip.
- *
- * Because CIA usage may change in the future, your code should use
- * a routine like this to find a free interval timer.
- *
- * Note that the routine takes a preference flag (which is used to
- * to indicate that you would prefer an interval timer on CIA-A).
- * If the flag is FALSE, it means that you would prefer an interval
- * timer on CIA-B.
- *
- *)
- PROCEDURE FindFreeTimer(VAR Ft: FreeTimer; PreferA: BOOLEAN): BOOLEAN;
- VAR
- CiaABase, CiaBBase: ADDRESS;
- BEGIN
- CiaABase:= EL.OpenResource(ADR(CR.ciaaName));
- CiaBBase:= EL.OpenResource(ADR(CR.ciabName));
-
- IF (CiaABase = NIL) OR (CiaBBase = NIL) THEN
- RETURN FALSE;
- END;
-
- IF PreferA THEN
- Ft.ciaBase:= CiaABase;
- Ft.ciaP:= ADR(HW.ciaa);
- ELSE
- Ft.ciaBase:= CiaBBase;
- Ft.ciaP:= ADR(HW.ciab);
- END;
- IF TryTimer(Ft) THEN RETURN TRUE; END;
-
- IF ~PreferA THEN
- Ft.ciaBase:= CiaABase;
- Ft.ciaP:= ADR(HW.ciaa);
- ELSE
- Ft.ciaBase:= CiaBBase;
- Ft.ciaP:= ADR(HW.ciab);
- END;
- IF TryTimer(Ft) THEN RETURN TRUE; END;
-
- RETURN FALSE;
-
- END FindFreeTimer;
-
-
-
-
-
- BEGIN
- IF FindFreeTimer(FreeT,TRUE) THEN
- FreeT.gotIt:= TRUE;
- ELSE
- Arts.Assert(TRUE, ADR("Could not allocate CIA-Timer."));
- FreeT.gotIt:= FALSE;
- END;
-
-
- CLOSE
- IF FreeT.gotIt THEN
- FreeT.gotIt:= FALSE;
- CR.RemICRVector(FreeT.ciaBase,FreeT.timerBit,NIL);
- END;
- END CiaTimer.
-